package com.item.model;

import com.google.common.collect.Maps;
import com.item.model.entity.WxUser;
import com.item.model.entity.dto.LayuiListPage;
import com.item.model.entity.result.ResultVo;
import com.item.model.service.UserService;
import com.item.model.service.WxOrderService;
import com.item.model.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.task.TaskExecutor;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池的两种用法
 * 分页查询的两种方式
 * @author zhang-rongyao
 * @version V1.0
 * @Package com.item.model
 * @date 2021/7/27 10:22
 */
@SpringBootTest
@Slf4j
public class GGG {

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    @Qualifier("activeExecutor") //指定找容器中方法名为activeExecutor的执行器
    TaskExecutor taskExecutor;

    @Autowired
    UserService userService;

    @Autowired
    WxOrderService orderService;

    /**
     * 结合rabbitmq使用
     * 要确保有队列和交换机，保证mq服务和web服务运行才能执行成功
     * @return
     */
    @Test
    public String method1() {
        int skillNum = 2;
        final CountDownLatch latch = new CountDownLatch(skillNum);
        log.info("开始");
        for (int i = 0; i < skillNum; i++) {
            int finalI = i;
            Runnable task = () -> {
                // TODO 业务：测试同时退款
                String messageId = String.valueOf(UUID.randomUUID());
                String createTime = DateUtil.getFormatDateTime(new Date());
                Map<String, Object> map = new HashMap<>();
                map.put("messageId", messageId);
//                map.put("order_no","AQAApkIKIb1-FTYJBnDxBOhoOdtf");
                map.put("order_no","test1");
                map.put("createTime", createTime);
                //将消息携带绑定键值：directRouting 发送到交换机directExchange
                rabbitTemplate.convertAndSend("directExchange", "directRouting", map);
                log.info("用户:[{}] 发起退款申请", finalI);
                //计数器减一
                latch.countDown();
            };
            taskExecutor.execute(task);
        }
        try {
            latch.await();// 等待所有人任务结束
            log.info("一共:[{}]个退款申请", skillNum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Result.ok()";
    }

    /**
     * 多线程使用的方式案例
     * 总执行时间小于每个方法执行消耗的时间
     * 使用时合理分配线程池中的核心线程数：corePoolSize
     *
     */
    @Test
    public void method2(){
        Map<String, Object> map = new HashMap<>(2);
        //开启4个任务
        int taskNum = 4;
        //线程计数器（等待所有线程执行完统一返回）
        final CountDownLatch latch = new CountDownLatch(taskNum);
        log.info("开始");
        //记录开始时间
        long startTime=System.currentTimeMillis();

        //任务一
        taskExecutor.execute(()->{
            try {
                System.out.println("正在统计新增用户数量");
                Thread.sleep(5000);//任务执行需要3秒
                //service调用
                //map.put("HandlingRecord", legalLitigationService.findHandlingRecordByAssociationId(associationId));
                map.put("userNumber",1);
                System.out.println("统计新增用户数量完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //标记已经完成一个任务
                latch.countDown();
            }
        });
        //任务二
        taskExecutor.execute(()->{
            try {
                System.out.println("正在统计订单数量");
                Thread.sleep(4000);//任务执行需要3秒
                //service调用
                //map.put("HandlingRecord", legalLitigationService.findHandlingRecordByAssociationId(associationId));
                map.put("countOrder",2);
                System.out.println("统计订单数量完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //标记已经完成一个任务
                latch.countDown();
            }
        });
        //任务三
        taskExecutor.execute(()->{
            try {
                System.out.println("正在商品销量");
                Thread.sleep(3000);//任务执行需要3秒
                //service调用
                //map.put("HandlingRecord", legalLitigationService.findHandlingRecordByAssociationId(associationId));
                map.put("countGoods",3);
                System.out.println("统计商品销量完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //标记已经完成一个任务
                latch.countDown();
            }
        });
        //任务四
        taskExecutor.execute(()->{
            try {
                System.out.println("正在总销售额");
                Thread.sleep(6000);//任务执行需要3秒
                //service调用
                //map.put("HandlingRecord", legalLitigationService.findHandlingRecordByAssociationId(associationId));
                map.put("countmoney",4);
                System.out.println("统计销售额完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //标记已经完成一个任务
                latch.countDown();
            }
        });

        try {
            latch.await();// 等待所有任务结束,唤醒main主线程
            long endTime=System.currentTimeMillis();//记录结束时间
            System.out.println("------统计指标全部完成--------");
            System.out.println("统计结果为："+map.toString());
            System.out.println("任务总执行时间为"+(endTime-startTime)/1000+"秒");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }



    /**
     * 多线程使用的方式案例
     * 总执行时间小于每个方法执行消耗的时间
     * 使用时合理分配线程池中的核心线程数：corePoolSize
     *
     */
    @Test
    public void method3(){
        Map<String, Object> map = new HashMap<>(2);
        //开启2个任务
        int taskNum = 2;
        //线程计数器（等待所有线程执行完统一返回）
        final CountDownLatch latch = new CountDownLatch(taskNum);
        log.info("开始");
        //记录开始时间
        long startTime=System.currentTimeMillis();

        //任务一
        taskExecutor.execute(()->{
            try {
                System.out.println("正在统计用户数量");
                Thread.sleep(5000);//任务执行需要3秒
                //service调用
                map.put("userList", userService.getAllUsers(1,20));
                System.out.println("统计用户数量完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //标记已经完成一个任务
                latch.countDown();
            }
        });
        //任务二
        taskExecutor.execute(()->{
            try {
                System.out.println("正在统计订单数量");
                Thread.sleep(4000);//任务执行需要3秒
                HashMap<String, Object> params = Maps.newHashMap();
                params.put("page",1);
                params.put("limit",20);
                params.put("orderTimeFrom","2020-07-23 10:15:05");
                params.put("orderTimeTo","2020-07-23 10:15:05");
                //service调用
                map.put("countOrder", orderService.getPageList(params));
                System.out.println("统计订单数量完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //标记已经完成一个任务
                latch.countDown();
            }
        });

        try {
            latch.await();// 等待所有任务结束,唤醒main主线程
            long endTime=System.currentTimeMillis();//记录结束时间
            System.out.println("------统计指标全部完成--------");
            System.out.println("统计结果为："+map.toString());
            System.out.println("任务总执行时间为"+(endTime-startTime)/1000+"秒");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 分页查询案例二
     * 联合查询
     */
    @Test
    public void testss(){
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("page",1);
        params.put("limit",20);
        params.put("orderTimeFrom","2020-07-23 10:15:05");
        params.put("orderTimeTo","2020-07-23 10:15:05");
        //service调用
        ResultVo pageList = orderService.getPageList(params);
        System.out.println(pageList);
    }


    /**
     * 分页查询案例一
     * 单表查询
     */
    @Test
    public void sfda(){
        LayuiListPage<WxUser> allUsers = userService.getAllUsers(1, 20);
        System.out.println(allUsers);
    }
}
